package com.zsd.android.okhttplib;

import android.support.annotation.NonNull;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Dispatcher {

    //同时访问任务，最大限制数
    private int maxRequests;
    //同时访问同一个服务器域名，最大限制数
    private int maxRequestsPerHost;
    //存储运行的队列
    private Deque<RealCall.AsyncCall> runningAsyncCalls;
    //存储等待的队列
    private Deque<RealCall.AsyncCall> readyAsyncCalls;

    public Dispatcher() {
        maxRequests = 64;
        maxRequestsPerHost = 5;
        runningAsyncCalls = new ArrayDeque<>();
        readyAsyncCalls = new ArrayDeque<>();
    }

    public void enqueue(RealCall.AsyncCall call) {
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
            //先把任务加入的运行队列中
            runningAsyncCalls.add(call);
            //然后再开始执行...
            executorService().execute(call);
        } else {
            //加入到等待队列
            readyAsyncCalls.add(call);
        }
    }

    /**
     * 线程池缓存方案
     * @return
     */
    private ExecutorService executorService() {
        ExecutorService service = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
                new ThreadFactory() {
                    @Override
                    public Thread newThread(@NonNull Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName("");
                        thread.setDaemon(false);
                        return thread;
                    }
                });
        return service;
    }

    /**
     * 判断AsyncCall中的Host，在运行的队列中，计数，然后放回
     *
     * 参数AsyncCall.Request.Host == runningAsyncCalls.for{}
     *
     * @param call
     * @return
     */
    private int runningCallsForHost(RealCall.AsyncCall call) {
        int count = 0;
        if (runningAsyncCalls.isEmpty()) {
            return 0;
        }

        SocketRequestServer server = new SocketRequestServer();

        //遍历运行队列里的所有任务，取出任务host == call.host, count + 1
        for (RealCall.AsyncCall runningAsyncCall : runningAsyncCalls) {
            //取出任务host == call.host, count + 1
            if (server.getHost(runningAsyncCall.getRequest()).equals(call.getRequest())) {
                count++;
            }
        }
        return count;
    }

    /**
     * 1. 移除运行完成的任务
     * 2. 把等待队列中所有的任务取出来执行 AsyncCall.run(), finished();
     *
     * @param call
     */
    public void finished(RealCall.AsyncCall call) {
        //当前运行的任务给回收
        runningAsyncCalls.remove(call);
        //考虑等待队列里面是否有任务，如果有任务是需要执行的
        if (readyAsyncCalls.isEmpty()) {
            return;
        }
        //把等待队列中的任务给移动到运行队列中
        for (RealCall.AsyncCall readyAsyncCall : readyAsyncCalls) {
            //从等待队列中移除
            readyAsyncCalls.remove(readyAsyncCall);
            //加入到运行队列中
            runningAsyncCalls.add(readyAsyncCall);
            //开始执行任务
            executorService().execute(readyAsyncCall);
        }
    }
}
